package com.sneakxy.mybase4j.base.service;

import java.io.Serializable;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;

import com.sneakxy.mybase4j.base.bean.TimeEntity;
import com.sneakxy.mybase4j.base.provider.IBaseProvider;
import com.sneakxy.mybatis.commons.repository.query.domain.Criteria;

/**
 * @author 潜行的青衣
 * @see
 */
public abstract class BaseService<T, ID extends Serializable, P extends IBaseProvider<T, ID>> implements IBaseService<T, ID> {
	
	public List<T> findAll() {
		return this.getProvider().findAll();
	}

	/* (non-Javadoc)
	 * @see com.nsxy.common.service.IBaseService#findAll(org.springframework.data.domain.Sort)
	 */
	@Override
	public List<T> findAll(Sort sort) {
		return this.getProvider().findAll(sort);
	}

	/* (non-Javadoc)
	 * @see com.nsxy.common.service.IBaseService#findAll(java.lang.Iterable)
	 */
	@Override
	public List<T> findAll(Iterable<ID> ids) {
		return this.getProvider().findAll(ids);
	}
	
	/* (non-Javadoc)
	 * @see com.nsxy.common.service.IBaseService#findAll(org.springframework.data.domain.Pageable)
	 */
	@Override
	public Page<T> findAll(Pageable pageable) {
		return this.getProvider().findAll(pageable);
	}
	
	/* (non-Javadoc)
	 * @see com.nsxy.common.service.IBaseService#findOne(java.io.Serializable)
	 */
	@Override
	public T findOne(ID id) {
		return this.getProvider().findOne(id);
	}

	/* (non-Javadoc)
	 * @see com.nsxy.common.service.IBaseService#exists(java.io.Serializable)
	 */
	@Override
	public boolean exists(ID id) {
		return this.getProvider().exists(id);
	}

	/* (non-Javadoc)
	 * @see com.nsxy.common.service.IBaseService#findOne(com.sneakxy.mybatis.commons.repository.query.domain.Criteria)
	 */
	@Override
	public T findOne(Criteria<T> criteria) {
		return this.getProvider().findOne(criteria);
	}

	/* (non-Javadoc)
	 * @see com.nsxy.common.service.IBaseService#findAll(com.sneakxy.mybatis.commons.repository.query.domain.Criteria)
	 */
	@Override
	public List<T> findAll(Criteria<T> criteria) {
		return this.getProvider().findAll(criteria);
	}

	/* (non-Javadoc)
	 * @see com.nsxy.common.service.IBaseService#findAll(com.sneakxy.mybatis.commons.repository.query.domain.Criteria, org.springframework.data.domain.Pageable)
	 */
	@Override
	public Page<T> findAll(Criteria<T> criteria, Pageable pageable) {
		return this.getProvider().findAll(criteria, pageable);
	}

	/* (non-Javadoc)
	 * @see com.nsxy.common.service.IBaseService#findAll(com.sneakxy.mybatis.commons.repository.query.domain.Criteria, org.springframework.data.domain.Sort)
	 */
	@Override
	public List<T> findAll(Criteria<T> criteria, Sort sort) {
		return this.getProvider().findAll(criteria, sort);
	}

	/* (non-Javadoc)
	 * @see com.nsxy.common.service.IBaseService#save(java.lang.Object)
	 */
	@Override
	public <S extends T> S save(S entity) {
		if(entity instanceof TimeEntity) {
			TimeEntity timeEntity = (TimeEntity) entity;
			String time = DateFormatUtils.format(Calendar.getInstance(), "yyyy-MM-dd HH:mm:ss");
			if(StringUtils.isBlank(timeEntity.getCreatetime())) {
				timeEntity.setCreatetime(time);
			}
			timeEntity.setUpdatetime(time);
		}
		return this.getProvider().save(entity);
	}

	/* (non-Javadoc)
	 * @see com.nsxy.common.service.IBaseService#save(java.lang.Iterable)
	 */
	@Override
	public <S extends T> List<S> save(Iterable<S> entities) {
		String time = DateFormatUtils.format(Calendar.getInstance(), "yyyy-MM-dd HH:mm:ss");
		Iterator<S> it = entities.iterator();
		S entity = null;
		TimeEntity timeEntity = null;
		while(it.hasNext()) {
			entity = it.next();
			if(entity instanceof TimeEntity) {
				timeEntity = (TimeEntity) entity;
				if(StringUtils.isBlank(timeEntity.getCreatetime())) {
					timeEntity.setCreatetime(time);
				}
				timeEntity.setUpdatetime(time);
			}
		}
		return this.getProvider().save(entities);
	}
	
	/* (non-Javadoc)
	 * @see com.nsxy.common.service.IBaseService#delete(java.io.Serializable)
	 */
	@Override
	public void delete(ID id) {
		this.getProvider().delete(id);
	}

	/* (non-Javadoc)
	 * @see com.nsxy.common.service.IBaseService#delete(java.lang.Object)
	 */
	@Override
	public void delete(T entity) {
		this.getProvider().delete(entity);
	}

	/* (non-Javadoc)
	 * @see com.nsxy.common.service.IBaseService#delete(java.lang.Iterable)
	 */
	@Override
	public void delete(Iterable<? extends T> entities) {
		this.getProvider().delete(entities);
	}

	/* (non-Javadoc)
	 * @see com.nsxy.common.service.IBaseService#deleteAll()
	 */
	@Override
	public void deleteAll() {
		this.getProvider().deleteAll();
	}

	public long count(Criteria<T> criteria) {
		return this.getProvider().count(criteria);
	}

	/* (non-Javadoc)
	 * @see com.nsxy.common.service.IBaseService#count()
	 */
	@Override
	public long count() {
		return this.getProvider().count();
	}
	
	public abstract P getProvider();

}
